package com.sunlake.spring.main.common.model.pay.controller;

import cn.hutool.extra.qrcode.QrCodeUtil;
import com.alipay.api.AlipayApiException;
import com.sunlake.spring.main.common.model.pay.dto.PayRequestDTO;
import com.sunlake.spring.main.common.model.pay.service.PayService;
import com.sunlake.spring.main.common.response.R;
import com.sunlake.spring.main.model.account.mapper.RechargeBillsMapper;
import com.sunlake.spring.main.model.account.po.RechargeBills;
import com.sunlake.spring.main.model.account.service.AccountService;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * @author liuha
 */
@RestController
@Slf4j
@RequestMapping("/api")
public class PayController {

    @Autowired
    private PayService payService;
    @Autowired
    private RechargeBillsMapper rechargeBillsMapper;
    @Autowired
    private AccountService accountService;
    @GetMapping("/pay")
    public void getPayQrCode(@RequestParam(required = false) String subject,
                             @RequestParam(required = false) String body,
                             @RequestParam(required = false) String totalAmount,
                             @RequestParam(required = false) String rechargeNo,
                             HttpServletResponse response) throws Exception {
        response.setContentType("image/png");

        PayRequestDTO payRequestDTO = new PayRequestDTO();
        if (rechargeNo != null && !rechargeNo.isEmpty()) {
            RechargeBills rechargeBill = rechargeBillsMapper.selectByRechargeNo(rechargeNo);
            if (rechargeBill != null) {
                subject = subject != null && !subject.isEmpty() ? subject : "账户充值";
                body = body != null && !body.isEmpty() ? body : "账户余额充值";
                totalAmount = rechargeBill.getAmount().toString();

                payRequestDTO.setOutTradeNo(rechargeNo);
            } else {
                response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
                response.getWriter().write("无效的充值单号");
                return;
            }
        }

        payRequestDTO.setSubject(subject);
        payRequestDTO.setBody(body);
        payRequestDTO.setTotalAmount(totalAmount);
        payRequestDTO.setTimeoutExpress("90m");

        try {
            // 使用DTO调用服务层生成支付二维码
            String qrCode = payService.generatePayQrCode(payRequestDTO);
            response.setContentType("image/png");
            QrCodeUtil.generate(qrCode, 300, 300, "png", response.getOutputStream());
        } catch (AlipayApiException e) {
            log.error("支付宝接口调用异常：", e);
            response.getWriter().write("支付请求异常：" + e.getMessage());
        } catch (IOException e) {
            log.error("输出二维码异常：", e);
            throw e;
        }
    }

    @PostMapping("/pay")
    public void payWithDto(@RequestBody PayRequestDTO payRequestDTO, HttpServletResponse response) throws Exception {
        try {
            // 调用服务层生成支付二维码
            String qrCode = payService.generatePayQrCode(payRequestDTO);

            // 输出二维码图片
            response.setContentType("image/png");
            QrCodeUtil.generate(qrCode, 300, 300, "png", response.getOutputStream());
        } catch (AlipayApiException e) {
            log.error("支付宝接口调用异常：", e);
            response.getWriter().write("支付请求异常：" + e.getMessage());
        } catch (IOException e) {
            log.error("输出二维码异常：", e);
            throw e;
        }
    }
    /**
     * 支付宝异步通知接口
     */
    @PostMapping("/callback")
    public String payNotify(HttpServletRequest request) {
        try {
            // 获取支付宝通知参数
            Map<String, String> params = new HashMap<>();
            request.getParameterMap().forEach((key, values) -> {
                if (values != null && values.length > 0) {
                    params.put(key, values[0]);
                }
            });

            // 调用服务层处理支付通知
            boolean success = payService.handlePayNotify(params);

            return success ? "success" : "fail";
        } catch (Exception e) {
            log.error("处理支付宝通知异常：", e);
            return "fail";
        }
    }
    @GetMapping("/pay/check-status")
    public R checkPayStatus(@RequestParam String rechargeNo) {
        Map<String, Object> data = new HashMap<>();
        try {
            // 1. 查询数据库中的充值记录
            RechargeBills rechargeBill = rechargeBillsMapper.selectByRechargeNo(rechargeNo);
            if (rechargeBill == null) {
                return R.error(404, "充值订单不存在");
            }

            // 2. 如果订单已经不是待支付状态，直接返回当前状态
            if (!"PENDING".equals(rechargeBill.getStatus())) {
                data.put("status", rechargeBill.getStatus());
                return R.ok(200, "订单已处理", data);
            }

            // 3. 调用支付宝接口查询真实支付状态
            String tradeStatus = payService.queryTradeStatus(rechargeNo);
            log.info("主动查询支付状态结果：订单号={}, 支付宝状态={}", rechargeNo, tradeStatus);

            // 4. 如果支付成功，直接更新余额和订单状态
            if ("TRADE_SUCCESS".equals(tradeStatus) || "TRADE_FINISHED".equals(tradeStatus)) {
                // 直接调用AccountService更新余额，而不是通过消息队列
                String mockTransactionNo = "MOCK" + System.currentTimeMillis();
                boolean updateResult = accountService.updateBalanceAfterPayment(rechargeNo, mockTransactionNo);

                if (updateResult) {
                    // 重新查询更新后的状态
                    rechargeBill = rechargeBillsMapper.selectByRechargeNo(rechargeNo);
                    data.put("status", rechargeBill.getStatus());
                    return R.ok(200, "支付成功，已更新订单状态和余额", data);
                } else {
                    return R.error(500, "支付成功，但更新订单状态失败");
                }
            } else if ("WAIT_BUYER_PAY".equals(tradeStatus)) {
                data.put("status", "PENDING");
                return R.ok(200, "等待支付", data);
            } else {
                data.put("status", "PENDING");
                return R.ok(200, "支付未完成", data);
            }
        } catch (Exception e) {
            log.error("主动查询支付状态异常：", e);
            return R.error(500, "查询支付状态异常：" + e.getMessage());
        }
    }
}
